package com.humble.vichatbackend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.humble.vichatbackend.common.*;
import com.humble.vichatbackend.constant.TeamConstant;
import com.humble.vichatbackend.constant.UserConstant;
import com.humble.vichatbackend.exception.BusinessException;
import com.humble.vichatbackend.mapper.TeamMapper;
import com.humble.vichatbackend.model.domain.Team;
import com.humble.vichatbackend.model.domain.UserTeam;
import com.humble.vichatbackend.model.enums.ErrorCode;
import com.humble.vichatbackend.model.vo.UserTeamVO;
import com.humble.vichatbackend.model.vo.UserVO;
import com.humble.vichatbackend.service.TeamService;
import com.humble.vichatbackend.service.UserService;
import com.humble.vichatbackend.service.UserTeamService;
import com.humble.vichatbackend.web_socket.ChatSocket;
import com.humble.vichatbackend.web_socket.ChatSocketManager;
import com.humble.vichatbackend.web_socket.ChatSocketUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import jakarta.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author che
 * @description 针对表【team(队伍)】的数据库操作Service实现
 * @createDate 2025-07-22 10:04:28
 */
@Service
@Slf4j
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
        implements TeamService {

    @Resource
    TeamMapper teamMapper;

    @Resource
    UserTeamService userTeamService;

    @Resource
    UserService userService;

    private static String salt = "HUMBLETEAM";

    @Override
    @Transactional
    public Long addTeam(TeamAddRequest teamAddRequest, UserVO currentUser) {

        String name = teamAddRequest.getName();
        String description = teamAddRequest.getDescription();
        Integer maxNum = teamAddRequest.getMaxNum();
        Date expireTime = teamAddRequest.getExpireTime();
        Integer status = teamAddRequest.getStatus();
        String password = teamAddRequest.getPassword();

        if (StringUtils.isBlank(name) || maxNum == null || status == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        if (maxNum <= 0) {
            throw new BusinessException("队伍最大人数应大于1", 40000);
        }
        if (name.isEmpty() || name.length() > 20) {
            throw new BusinessException("队伍名长度不合规定,长度限制：[1,20]", 40000);
        }
        if (description.isEmpty() || description.length() > 100) {
            throw new BusinessException("队伍描述长度不合规定,长度限制：[1,100]", 40000);
        }
        if (expireTime != null && expireTime.getTime() < System.currentTimeMillis()) {
            throw new BusinessException("过期时间不得早于当下", 40000);
        }
        if (status == 2 && (StringUtils.isBlank(password) || password.length() > 20)) {
            throw new BusinessException("加密队伍必须设置长度相符的密码，长度限制[1,20],", 40000);
        }
        // 获取加密后密码
        String enctypePassword = null;
        if (!StringUtils.isBlank(password)) {
            enctypePassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        }

        // 限制用户创建队伍的最大数量
        Long id = currentUser.getId();
        Long teamCount = teamMapper.selectCount(new QueryWrapper<Team>().lambda().eq(Team::getUserId, id));
        if (teamCount >= 5) {
            throw new BusinessException("用户创建队伍超过最大限制", 40301);
        }


        Team team = new Team();
        team.setName(name);
        team.setDescription(description);
        team.setMaxNum(maxNum);
        team.setExpireTime(expireTime);
        team.setUserId(id);
        team.setStatus(status);
        team.setPassword(enctypePassword);

        log.info("新增队伍开始，队长：{}，队伍信息：{}", currentUser.getUsername(), team.toString());
        int result = teamMapper.insert(team);
        Long teamId = team.getId();
        // 创建者加入队伍
        if (result <= 0 || teamId == null) {
            throw new BusinessException("创建队伍失败,系统内部异常", 50000);
        }

        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(id);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());
        boolean save = userTeamService.save(userTeam);
        if (!save) {
            throw new BusinessException("创建队伍失败,系统内部异常", 50000);
        }
        if(!ChatSocketUtil.createChat(currentUser.getId(),teamId)){
            throw new BusinessException("创建聊台室失败",50000);
        }
        return teamId;
    }

    @Override
    public Boolean updateTeam(TeamUpdateRequest teamUpdateRequest, UserVO currentUser) {
        if (currentUser.getId() == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        if (currentUser.getId().equals(teamUpdateRequest.getUserId()) && currentUser.getId() != UserConstant.ADMIN_ROLE) {
            throw new BusinessException(ErrorCode.NO_AUTH);
        }

        Long id = teamUpdateRequest.getId();
        String name = teamUpdateRequest.getName();
        String description = teamUpdateRequest.getDescription();
        Integer maxNum = teamUpdateRequest.getMaxNum();
        Date expireTime = teamUpdateRequest.getExpireTime();
        Integer status = teamUpdateRequest.getStatus();
        String password = teamUpdateRequest.getPassword();
        Long hasJoinNum = teamUpdateRequest.getHasJoinNum();

        // 查询原信息
        Team team = teamMapper.selectById(id);
        if (team == null) {
            throw new BusinessException("不存在该队伍信息", 40000);
        }

        if (name != null && name.length() > 20) {
            throw new BusinessException("队伍名长度不合规定,长度限制：[1,20]", 40000);
        }
        if (description != null && description.length() > 100) {
            throw new BusinessException("队伍描述长度不合规定,长度限制：[1,100]", 40000);
        }
        if (expireTime != null && expireTime.getTime() < System.currentTimeMillis()) {
            throw new BusinessException("过期时间不得早于当下", 40000);
        }
        if (team.getStatus() == 2) {
            if (status == 2 && !StringUtils.isBlank(password) && password.length() > 20) {
                throw new BusinessException("加密队伍必须设置长度相符的密码，长度限制[1,20]", 40000);
            }
        } else {
            if (status == 2 && (StringUtils.isBlank(password) || password.length() > 20)) {
                throw new BusinessException("加密队伍必须设置长度相符的密码，长度限制[1,20]", 40000);
            }
        }
        // 最大人数不得小于当前小队人数
        long userCount = userTeamService.count(new QueryWrapper<UserTeam>().eq("team_id", id));
        if (maxNum < userCount) {
            throw new BusinessException("队伍人数不得小于现有人数", 40000);
        }

        Team updateTeam = new Team();
        updateTeam.setName(StringUtils.isBlank(name) ? null : name);
        updateTeam.setDescription(StringUtils.isBlank(description) ? null : description);
        updateTeam.setMaxNum(maxNum);
        updateTeam.setExpireTime(expireTime);
        updateTeam.setUserId(null);
        updateTeam.setStatus(status);
        updateTeam.setPassword(password);
        updateTeam.setHasJoinNum(hasJoinNum);

        int count = teamMapper.update(updateTeam, new UpdateWrapper<Team>().eq("id", id));
        return count >= 0;
    }

    @Override
    public List<UserTeamVO> listTeams(TeamQueryRequest teamQueryRequest, Boolean isAdmin, Long currentUserId) {
        Long id = teamQueryRequest.getId();
        List<Long> idList = teamQueryRequest.getIdList();
        String searchText = teamQueryRequest.getSearchText();
        String name = teamQueryRequest.getName();
        String description = teamQueryRequest.getDescription();
        Integer maxNum = teamQueryRequest.getMaxNum();
        Long userId = teamQueryRequest.getUserId();
        Integer status = teamQueryRequest.getStatus();
//        int pageSize = teamQueryRequest.getPageSize();
//        int pageNum = teamQueryRequest.getPageNum();

        QueryWrapper<Team> teamQueryWrapper = new QueryWrapper<>();
        if (id != null && id != 0) {
            teamQueryWrapper.eq("id", id);
        }
        if (CollectionUtils.isNotEmpty(idList)) {
            teamQueryWrapper.in("id", idList);
        }
        if (StringUtils.isNotBlank(searchText)) {
            teamQueryWrapper.and(qw -> {
                qw.like("name", searchText).or().like("description", searchText);
            });
        }
        if (StringUtils.isNotBlank(name)) {
            teamQueryWrapper.like("name", name);
        }
        if (StringUtils.isNotBlank(description)) {
            teamQueryWrapper.like("description", description);
        }
        if (maxNum != null && maxNum > 0) {
            teamQueryWrapper.eq("maxNum", maxNum);
        }
        if (userId != null && userId > 0) {
            teamQueryWrapper.eq("user_id", userId);
        }
        if (status != null) {
            if (status == 2 && !isAdmin) {
                throw new BusinessException(ErrorCode.NO_AUTH);
            }
            teamQueryWrapper.eq("status", status);
        }
        teamQueryWrapper.gt("expire_time", new Date());
        List<Team> teams = teamMapper.selectList(teamQueryWrapper);

        Set<Long> joinSet = userTeamService.list(new QueryWrapper<UserTeam>().eq("user_id", currentUserId))
                .stream().map(UserTeam::getTeamId).collect(Collectors.toSet());

        return teams.stream().map(team -> {
            UserTeamVO tempVO = new UserTeamVO();
            BeanUtils.copyProperties(team, tempVO);
            tempVO.setCreateUser(UserVO.getSafeUser(userService.getById(tempVO.getUserId())));
            tempVO.setHasJoin(joinSet.contains(team.getId()));
            return tempVO;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public Boolean joinTeam(TeamJoinRequest teamJoinRequest, UserVO currentUser) {
        Long teamId = teamJoinRequest.getTeamId();
        String password = teamJoinRequest.getPassword();
        if (teamId == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        Team team = teamMapper.selectById(teamId);
        if (team == null) {
            throw new BusinessException("该队伍不存在", 40000);
        }
        Integer status = team.getStatus();
        if (Objects.equals(status, TeamConstant.SECRET_TEAM_STATUS)) {
            if (StringUtils.isBlank(password)) {
                throw new BusinessException(ErrorCode.NULL_ERROR);
            }
            String encPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
            if (!encPassword.equals(password)) {
                throw new BusinessException("队伍密码有误", 40000);
            }
        }
        // 保存关系
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(currentUser.getId());
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());
        boolean save = userTeamService.save(userTeam);
        team.setHasJoinNum(team.getHasJoinNum() + 1);

        int i = teamMapper.updateById(team);
        if(!ChatSocketUtil.joinChat(currentUser.getId(),teamId)){
            log.error("用户加入队伍聊天室是出现异常，异常聊天室teamId:{}",teamId);
            throw new BusinessException("加入队伍聊天室是出现异常",50000);
        }

        return save && i > 0;
    }

    @Override
    @Transactional
    public Boolean quitTeam(TeamQuitRequest teamQuitRequest, UserVO currentUser) {
        Long teamId = teamQuitRequest.getTeamId();
        boolean remove = userTeamService.remove(new QueryWrapper<UserTeam>().lambda().eq(UserTeam::getTeamId, teamId).eq(UserTeam::getUserId, currentUser.getId()));
        if (!remove) {
            throw new BusinessException("删除失败，你不在队伍中", 40000);
        }
        Team team = teamMapper.selectById(teamId);
        if (team == null) {
            throw new BusinessException("队伍不存在", 40000);
        }
        team.setHasJoinNum(team.getHasJoinNum() - 1);
        int update = teamMapper.updateById(team);

        if(!ChatSocketUtil.removeFromChat(currentUser.getId(),teamId)){
            log.error("用户退出队伍聊天室是出现异常，异常聊天室teamId:{}",teamId);
            throw new BusinessException("加入队伍聊天室是出现异常",50000);
        }
        return remove && update > 0;
    }

    @Override
    @Transactional
    public Boolean deleteTeam(Long id, UserVO currentUser) {
        if (currentUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN);
        }
        if (currentUser.getUserRole() != UserConstant.ADMIN_ROLE) {
            throw new BusinessException(ErrorCode.NO_AUTH);
        }

        boolean removeRelation = userTeamService.remove(new QueryWrapper<UserTeam>().eq("team_id", id));
        int removeTeam = teamMapper.deleteById(id);
        if (!removeRelation || removeTeam <= 0) {
            throw new BusinessException("删除失败", 40000);
        }
        ChatSocket remove = ChatSocketManager.CHAT_SOCKET_MAP.remove(id);
        if(remove==null){
            log.error("删除队伍出现异常,没有找到该聊天室:{}",id);
            throw new BusinessException("删除队伍出现异常",50000);
        }

        return true;
    }

    @Override
    public Page<Team> listTeamsByPage(TeamQueryRequest teamQueryRequest, Boolean isAdmin, Long currentUserId) {
        Long id = teamQueryRequest.getId();
        List<Long> idList = teamQueryRequest.getIdList();
        String searchText = teamQueryRequest.getSearchText();
        String name = teamQueryRequest.getName();
        String description = teamQueryRequest.getDescription();
        Integer maxNum = teamQueryRequest.getMaxNum();
        Long userId = teamQueryRequest.getUserId();
        Integer status = teamQueryRequest.getStatus();
        int pageSize = teamQueryRequest.getPageSize();
        int pageNum = teamQueryRequest.getPageNum();

        QueryWrapper<Team> teamQueryWrapper = new QueryWrapper<>();

        if (id != null && id != 0) {
            teamQueryWrapper.eq("id", id);
        }
        if (CollectionUtils.isNotEmpty(idList)) {
            teamQueryWrapper.in("id", idList);
        }
        if (StringUtils.isNotBlank(searchText)) {
            teamQueryWrapper.and(qw -> {
                qw.like("name", searchText).or().like("description", searchText);
            });
        }
        if (StringUtils.isNotBlank(name)) {
            teamQueryWrapper.like("name", name);
        }
        if (StringUtils.isNotBlank(description)) {
            teamQueryWrapper.like("description", description);
        }
        if (maxNum != null && maxNum > 0) {
            teamQueryWrapper.eq("maxNum", maxNum);
        }
        if (userId != null && userId > 0) {
            teamQueryWrapper.eq("userId", userId);
        }
        if (status != null) {
            if (status == 2 && !isAdmin) {
                throw new BusinessException(ErrorCode.NO_AUTH);
            }
            teamQueryWrapper.eq("status", status);
        }
        teamQueryWrapper.gt("expire_time", new Date());
        Page<Team> page = new Page<>(pageNum, pageSize);
        return teamMapper.selectPage(page, teamQueryWrapper);

        //
        // Set<Long> joinSet = userTeamService.list(new QueryWrapper<UserTeam>().eq("user_id", currentUserId))
        //         .stream().map(UserTeam::getTeamId).collect(Collectors.toSet());
        //
        // List<UserTeamVO> resultList = teams.stream().map(team -> {
        //     UserTeamVO tempVO = new UserTeamVO();
        //     BeanUtils.copyProperties(team, tempVO);
        //     tempVO.setCreateUser(UserVO.getSafeUser(userService.getById(tempVO.getUserId())));
        //     tempVO.setHasJoin(joinSet.contains(team.getId()));
        //     return tempVO;
        // }).collect(Collectors.toList());
        //
        // Page<UserTeamVO> resultPage = new Page<>(pageNum, pageSize);
        // resultPage.setRecords(resultList);
        // return resultPage;
    }
}




